package com.wxxymakers.grademark.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.wxxymakers.grademark.exception.ServiceException;
import com.wxxymakers.grademark.model.entity.WxIncident;
import com.wxxymakers.grademark.model.mapper.WxIncidentMapper;
import com.wxxymakers.grademark.utils.PageUtils;
import com.wxxymakers.grademark.utils.TimeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * @AUTHOR soft
 * @DATE 2018/12/22 23:21
 * @DESCRIBE 事件业务层
 */
@Service
public class WxIncidentService {

    @Autowired
    private WxIncidentMapper incidentMapper;

    @Autowired
    private WxItemRecordService recordService;

    @Transactional
    public boolean add(WxIncident incident) {
        verifySetStatus(incident); // 设置状态
        return incidentMapper.insert(incident) > 0;
    }

    @Transactional
    public boolean delete(int id) {
        return incidentMapper.deleteById(id) > 0;
    }

    @Transactional
    public boolean change(WxIncident incident) {
        if (incident.getId() != null && incident.getId() > 0) {
            verifySetStatus(incident); // 设置状态
            return incidentMapper.updateById(incident) > 0;
        }
        return false;
    }

    /**
     * 停止当前事件
     * @param id 事件id
     */
    @Transactional
    public boolean restart(int id) {
        WxIncident incident = findOne(id);
        if (TimeUtils.before(incident.getBeginTime())) {
            throw new ServiceException("现在开始是不是太早了，等等吧！");
        }
        if (TimeUtils.after(incident.getEndTime())) {
            throw new ServiceException("结束的事件无法开始！您可以修改结束时间。");
        }
        if (findBeganInc() != null) {
            throw new ServiceException("请先结束当前事件！");
        }
        incident.setStatus("1");
        incident.setName(null);
        return incidentMapper.updateById(incident) > 0;
    }

    /**
     * 停止当前事件
     * @param id 事件id
     */
    @Transactional
    public boolean stop(int id) {
        WxIncident incident = new WxIncident();
        incident.setStatus("2");
        incident.setId(id);
        return incidentMapper.updateById(incident) > 0;
    }

    /**
     * 获取一个已经开始的事件
     * @return 返回当前正在进行的事件 仅可有一个
     */
    public WxIncident findBeganInc() {
        WxIncident incident = new WxIncident();
        incident.setStatus("1");
        return incidentMapper.selectOne(new QueryWrapper<>(incident));
    }

    public WxIncident findOne(int id) {
        return incidentMapper.selectById(id);
    }

    /**
     * 判断事件是不是已经结束
     * @param id 事件id
     */
    public boolean isEnd(int id) {
        WxIncident incident = findOne(id);
        if (null == incident) {
            return false;
        }
        return TimeUtils.after(incident.getEndTime()) || "2".equals(incident.getStatus());
    }

    public List<WxIncident> list() {
        return incidentMapper.selectList(null);
    }

    /**
     * 分页查询 状态已大于为条件
     * @param page 页码
     * @param limit 尺寸
     * @param query 条件
     */
    @Deprecated
    public Page<WxIncident> page(int page, int limit, WxIncident query) {
        QueryWrapper<WxIncident> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("begin_time");
        if (query != null) {
            if (!StringUtils.isEmpty(query.getName())) wrapper.like("name", query.getName());
            if (!StringUtils.isEmpty(query.getStatus())) wrapper.ge("status", query.getStatus());
        }

        int total = incidentMapper.selectCount(wrapper);
        if (total > 0) {
            List<WxIncident> wxIncidents = incidentMapper.selectPage(PageUtils.rowBounds(page, limit), wrapper)
                    .getRecords();
            return PageUtils.page(wxIncidents, page, limit, total);
        }
        return null;
    }

    public Page<WxIncident> page(int page, int limit, String name, String status, Integer collegeId) {
        QueryWrapper<WxIncident> wrapper = new QueryWrapper<>();
        if (!StringUtils.isEmpty(name)) wrapper.lambda().like(WxIncident::getName, "%" + name + "%");
        if (!StringUtils.isEmpty(status)) {
            if ("0".equals(status)) {
                wrapper.lambda().eq(WxIncident::getStatus, status);
            } else {
                int st = Integer.parseInt(status);
                int o = st & 1;
                int t = st & 2;
                if (o != 0 && t != 0) {
                    wrapper.lambda().eq(WxIncident::getStatus, o).or().eq(WxIncident::getStatus, t);
                } else {
                    if (0 != o) {
                        wrapper.lambda().eq(WxIncident::getStatus, o);
                    }
                    if (0 != t) {
                        wrapper.lambda().eq(WxIncident::getStatus, t);
                    }
                }
            }
        }

        IPage<WxIncident> incidents = incidentMapper.selectPage(PageUtils.rowBounds(page, limit), wrapper);

        if (incidents != null && incidents.getTotal() > 0) {
            incidents.getRecords().forEach(incident->{
                long count = recordService.countByIIdAndCollegeId(incident.getId(), collegeId);
                incident.setPeopleNum(count);
            });
            return PageUtils.page(incidents.getRecords(), page, limit, incidents.getTotal());
        }
        return null;
    }

    /**
     * 验证时间合法性 同时设置事件状态
     * 限制：同一时段只能开始一个事件
     */
    private void verifySetStatus(WxIncident incident) {
        if (incident.getBeginTime().compareTo(incident.getEndTime()) > 0) {
            throw new ServiceException("结束时间怎么能在开始时间之前呢？");
        }
        if (incident.getBeginRange().compareTo(incident.getEndRange()) > 0) {
            throw new ServiceException("有效区间是不是反了？");
        }

        WxIncident beganInc = findBeganInc();
        if (beganInc != null && !beganInc.getId().equals(incident.getId())) { // 实现限制
            incident.setStatus("0");
        } else {
            if (TimeUtils.between(incident.getBeginTime(), incident.getEndTime())) {
                incident.setStatus("1");
            } else if (TimeUtils.before(incident.getBeginTime())) {
                incident.setStatus("0");
            } else {
                incident.setStatus("2");
            }
        }
    }
}
